package com.caltco.cargo.ops.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caltco.cargo.ops.auth.bo.AdminUserDetails;
import com.caltco.cargo.ops.common.exception.RRException;
import com.caltco.cargo.ops.common.utils.StringUtils;
import com.caltco.cargo.ops.modules.sys.dao.GetGanttDao;
import com.caltco.cargo.ops.modules.sys.dao.ProjectDao;
import com.caltco.cargo.ops.modules.sys.dao.TaskDao;
import com.caltco.cargo.ops.modules.sys.entity.*;
import com.caltco.cargo.ops.modules.sys.request.TaskRequest;
import com.caltco.cargo.ops.modules.sys.service.TaskFileService;
import com.caltco.cargo.ops.modules.sys.service.TaskService;
import com.caltco.cargo.ops.modules.sys.service.TaskUserService;
import com.caltco.cargo.ops.modules.sys.vo.ProjectVO;
import com.caltco.cargo.ops.modules.sys.vo.TaskGanttVO;
import com.caltco.cargo.ops.modules.sys.vo.TaskVO;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

@Service
public class TaskServiceImp extends ServiceImpl<TaskDao, Task> implements TaskService {
    private final TaskUserService taskUserService;
    private final TaskDao taskDao;
    private final ProjectDao projectDao;
    private final TaskFileService taskFileService;
    private final GetGanttDao getGanttDao;

    public TaskServiceImp(TaskUserService taskUserService, TaskDao taskDao, ProjectDao projectDao, TaskFileService taskFileService, GetGanttDao getGanttDao) {
        this.taskUserService = taskUserService;
        this.taskDao = taskDao;
        this.projectDao = projectDao;
        this.taskFileService = taskFileService;
        this.getGanttDao = getGanttDao;
    }

    public Long getUserIdByToken() {
        return ((AdminUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUserEntity().getUserId();
    }

    @Override
    public List<TaskVO> get(TaskRequest taskRequest) {
        Boolean isAsc;
        if (taskRequest.getOrderAsc() == null || taskRequest.getOrderAsc()) {
            isAsc = true;
        } else {
            isAsc = false;
        }

        List<TaskVO> taskVOS = taskDao.selectJoinList(TaskVO.class, new MPJLambdaWrapper<Task>()
                .select(Task::getId, Task::getUserId, Task::getProjectId, Task::getTaskName,
                        Task::getTaskEndTime, Task::getTaskStartTime, Task::getProcess,
                        Task::getTaskDescription, Task::getIsPublish, Task::getHandlerId, Task::getLevel)
                .selectAs("GROUP_CONCAT(DISTINCT t6.id)", TaskVO::getUserIdsString) // 查询 TaskUser 关联的所有 UserId
                .leftJoin(Project.class, Project::getId, Task::getProjectId)
                .leftJoin(TaskUser.class, TaskUser::getTaskId, Task::getId)
                .leftJoin(SysUserEntity.class, "t6", SysUserEntity::getId, TaskUser::getUserId)
                .leftJoin(ProjectUser.class, ProjectUser::getUserId, SysUserEntity::getId)
                .and(wrapper -> wrapper
                        .eq(Task::getIsPublish, 1)
                        .eq(Task::getProjectId, taskRequest.getProjectId())
                )
                .or(wrapper -> wrapper
                        .eq(SysUserEntity::getId, getUserIdByToken())
                        .eq(ProjectUser::getIsCreate, 1)
                        .eq(Task::getProjectId, taskRequest.getProjectId())
                )
                .like(StringUtils.isNotBlank(taskRequest.getTaskName()), Task::getTaskName, taskRequest.getTaskName())
                .groupBy(Task::getId, Task::getUserId, Task::getProjectId, Task::getTaskName,
                        Task::getTaskEndTime, Task::getTaskStartTime, Task::getProcess,
                        Task::getTaskDescription, Task::getIsPublish, Task::getHandlerId, Task::getLevel)
                .orderByAsc(isAsc, Task::getLevel)
                .orderByDesc(!isAsc, Task::getLevel));


        taskVOS.forEach(item -> {
            item.setUserIds(item.getUserIdListAsList());
        });

        return taskVOS;

    }

    @Override
    public List<TaskGanttVO> getGantt(TaskRequest taskRequest) {
        List<TaskGanttVO> taskGanttVOS;
        if (taskRequest.getIsProject() == null || taskRequest.getIsProject() == 1) {
            taskGanttVOS = getGanttDao.getGantt(taskRequest, null);
        } else {
            taskGanttVOS = getGanttDao.getGantt(taskRequest, getUserIdByToken());
        }

        return taskGanttVOS;
    }

    @Override
    public List<ProjectVO> getGanttProject(String taskName, Long projectId) {
        List<ProjectVO> projectVOS = projectDao.selectJoinList(ProjectVO.class, new MPJLambdaWrapper<Project>()
                .selectAll(Project.class) // 选择所有 Project 表字段
                .leftJoin(Task.class, Task::getProjectId, Project::getId)
                .leftJoin(ProjectUser.class, ProjectUser::getProjectId, Project::getId)
                .leftJoin(SysUserEntity.class, SysUserEntity::getId, ProjectUser::getUserId)
                .eq(SysUserEntity::getId, getUserIdByToken())
                .eq(projectId != null, Project::getId, projectId)
                .like(StringUtils.isNotBlank(taskName), Task::getTaskName, taskName)
                .groupBy(Project::getId, Project::getProjectName, Project::getDescription,
                        Project::getProjectEndTime, Project::getProjectStartTime,
                        Project::getIsDelete)); // 按所有字段分组

        return projectVOS;
    }

    @Override
    public TaskVO getMassage(Long id) {
        Task task = this.getById(id);
        if (task == null) {
            return null;
        }
        TaskVO taskVO = new TaskVO();
        BeanUtil.copyProperties(task, taskVO);
        return taskVO;
    }

    @Override
    public Boolean remove(Long id) {
        taskUserService.remove(new MPJLambdaWrapper<TaskUser>()
                .eq(TaskUser::getTaskId, id));
        return this.removeById(id);
    }

    @Override
    @Transactional
    public Boolean save(TaskRequest taskRequest, MultipartFile[] files, Long taskId) {
        Long handlerId = taskRequest.getHandlerId();
        if (handlerId == null) {
            throw new RRException("没有指定负责人");
        }
        taskRequest.setId(null);
        Task task = new Task();
        BeanUtil.copyProperties(taskRequest, task);
        this.save(task);
        if (files != null) {
            taskFileService.batchUploadFile(files, task.getId());
        }
        List<Long> userIds = taskRequest.getUserIds();
        List<TaskUser> taskUsers = new ArrayList<>();
        if (userIds.size() != 0) {
            userIds.forEach(item -> {
                TaskUser taskUser = new TaskUser();
                taskUser.setTaskId(task.getId());
                taskUser.setUserId(item);
                taskUser.setIsPublish(0);
                taskUsers.add(taskUser);
            });
        }
        TaskUser taskUser = new TaskUser();
        taskUser.setTaskId(task.getId());
        taskUser.setUserId(handlerId);
        taskUser.setIsPublish(1);
        taskUsers.add(taskUser);
        taskUserService.saveBatch(taskUsers);
        return true;
    }

    @Override
    @Transactional
    public Boolean update(TaskRequest taskRequest, MultipartFile[] files, Long taskId, List<String> fileIds) {
        Long handlerId = taskRequest.getHandlerId();
        if (handlerId == null) {
            throw new RRException("没有指定负责人");
        }
        if (taskRequest.getId() == null) {
            throw new RRException("id为空");
        }
        Task task = new Task();
        BeanUtil.copyProperties(taskRequest, task);
        this.updateById(task);
        if (files != null && taskId != null) {
            taskFileService.batchUploadFile(files, taskId);
        }
        if (fileIds != null && fileIds.size() > 0) {
            taskFileService.deleteFiles(fileIds);
        }

        List<Long> userIds = taskRequest.getUserIds();
        List<TaskUser> taskUsers = new ArrayList<>();

        // 移除原来的数据
        taskUserService.remove(new MPJLambdaWrapper<TaskUser>()
                .eq(TaskUser::getTaskId, task.getId()));

        if (userIds.size() != 0) {
            userIds.forEach(item -> {
                TaskUser taskUser = new TaskUser();
                taskUser.setTaskId(task.getId());
                taskUser.setUserId(item);
                taskUsers.add(taskUser);
            });
        }
        TaskUser taskUser = new TaskUser();
        taskUser.setTaskId(task.getId());
        taskUser.setUserId(handlerId);
        taskUser.setIsPublish(1);
        taskUsers.add(taskUser);
        taskUserService.saveBatch(taskUsers);
        taskUserService.saveOrUpdateBatch(taskUsers);
        return true;
    }
}
